package com.raincat.tools.nettools;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Pair;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Map;

/**
 * <pre>
 *     author : RainCat
 *     org    : Shenzhen JingYu Network Technology Co., Ltd.
 *     e-mail : nining377@gmail.com
 *     time   : 2020/03/23
 *     desc   : HTTP连接
 *     version: 1.0
 * </pre>
 */
class ConnectHttp extends Connect {
    private DataAsyncTask task;

    @Override
    void init(Request request) {
        super.init(request);
        if (task == null)
            task = new DataAsyncTask();
        task.executeOnExecutor(exec, request);
    }

    @SuppressLint("StaticFieldLeak")
    private class DataAsyncTask extends AsyncTask<Request, Integer, Pair<Integer, String>> {
        @Override
        protected Pair<Integer, String> doInBackground(Request... request) {
            if (isCancelled())
                return null;
            return connect(request[0]);
        }

        @Override
        protected void onPostExecute(Pair<Integer, String> result) {
            if (!getResult(result, task) && !isCancelled()) {
                Handler handler = new Handler(request.context.get().getMainLooper());
                handler.post(new Runnable() {
                    public void run() {
                        init(request);
                    }
                });
            }
        }
    }

    private Pair<Integer, String> connect(Request request) {
        String result;
        int errorCode = 0;

        HttpURLConnection connection = null;
        InputStream is = null;
        try {
            URL url = new URL(request.url);// 获得URL对象
            connection = (HttpURLConnection) url.openConnection();// 获得HttpURLConnection对象
            connection.setRequestMethod(request.method);// 请求方式POST
            connection.setUseCaches(false);// 不使用缓存
            connection.setConnectTimeout(request.connectTimeout);// 设置超时时间
            connection.setReadTimeout(request.readTimeout);// 设置读取超时时间
            connection.setChunkedStreamingMode(0);//设置超时不自动重试
            connection.setInstanceFollowRedirects(true);// 自动执行 http 重定向
            connection.setRequestProperty("Charset", "UTF-8");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Cookie", request.cookie);
            if (request.headers != null) {
                for (Map.Entry<String, Object> entry : request.headers.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue().toString());
                }
            }
            if (request.method.equals("POST")) {
                connection.setDoInput(true);
                connection.setDoOutput(true);
            }
            connection.connect();
            if (request.method.equals("POST")) {
                DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                out.writeBytes(request.param);
                out.flush();
                out.close();
            }
            if (connection.getHeaderField("Set-Cookie") != null && connection.getHeaderField("Set-Cookie").length() != 0)
                saveCookie(request.context.get(), connection.getHeaderField("Set-Cookie"));
            // 响应码是否为200
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK)
                is = connection.getInputStream();
            else {
                is = connection.getErrorStream();
                errorCode = connection.getResponseCode();
            }
            // 获得输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            // 包装字节流为字符流
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            result = response.toString();
        } catch (ConnectException e) {
            errorCode = 1;
            e.printStackTrace();
            result = e.toString();
        } catch (SocketException e) {
            errorCode = 2;
            e.printStackTrace();
            result = e.toString();
        } catch (OutOfMemoryError e) {
            errorCode = 3;
            e.printStackTrace();
            result = e.toString();
        } catch (SocketTimeoutException e) {
            errorCode = 4;
            e.printStackTrace();
            result = e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            errorCode = -1;
            result = e.toString();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return new Pair<>(errorCode, result);
    }

    void cancel() {
        if (task != null && task.getStatus() == AsyncTask.Status.RUNNING)
            task.cancel(true);
    }
}
